"""
RagFlow 客户端 GUI 批量上传选项卡组件
"""

import os
from PySide6.QtCore import Qt, Signal
from PySide6.QtWidgets import (
    QWidget, QVBoxLayout, QHBoxLayout, QGridLayout,
    QLabel, QLineEdit, QPushButton, QFileDialog,
    QListWidget, QMessageBox, QProgressDialog, QSpinBox,
    QComboBox
)

from ragflow_client.api import RagFlowAPI

from ragflow_client.config import RagFlowConfig
from ragflow_client.utils.file_util import get_files
from ragflow_client.gui.components.threads import UploadFilesThread


class BatchUploadTabWidget(QWidget):
    """批量上传选项卡组件"""
    
    # 定义信号
    log_message = Signal(str)
    upload_result = Signal(int, int)
    show_datasets_signal = Signal()
    
    def __init__(self, parent=None):
        """初始化批量上传选项卡组件"""
        super().__init__(parent)
        self.parent = parent
        self.current_thread = None
        self.setup_ui()
    
    def setup_ui(self):
        """创建界面"""
        # 创建布局
        layout = QGridLayout(self)
        
        # 知识库选择
        layout.addWidget(QLabel("目标知识库:"), 0, 0)
        
        kb_layout = QHBoxLayout()
        layout.addLayout(kb_layout, 0, 1)
        
        # 创建知识库下拉框
        self.kb_combo = QComboBox()
        self.kb_combo.setMinimumWidth(300)  # 设置最小宽度
        self.kb_combo.setSizeAdjustPolicy(QComboBox.AdjustToContents)  # 根据内容调整大小
        kb_layout.addWidget(self.kb_combo)
        
        # 刷新知识库列表按钮
        refresh_kb_button = QPushButton("刷新列表")
        refresh_kb_button.clicked.connect(self.refresh_kb_list)
        kb_layout.addWidget(refresh_kb_button)
        
        # 添加弹性空间
        kb_layout.addStretch()
        
        # 隐藏的知识库ID和名称字段，用于存储选中的知识库信息
        self.kb_id = ""
        self.kb_name = ""
        
        # 文档目录
        layout.addWidget(QLabel("文档目录:"), 1, 0)
        
        dir_layout = QHBoxLayout()
        layout.addLayout(dir_layout, 1, 1)
        
        self.doc_dir_edit = QLineEdit()
        dir_layout.addWidget(self.doc_dir_edit)
        
        browse_button = QPushButton("浏览...")
        browse_button.clicked.connect(self.browse_directory)
        dir_layout.addWidget(browse_button)
        
        # 文档后缀
        layout.addWidget(QLabel("文档后缀:"), 2, 0)
        self.doc_suffix_edit = QLineEdit()
        self.doc_suffix_edit.setText("md,txt,pdf,docx")
        layout.addWidget(self.doc_suffix_edit, 2, 1)
        
        # 解析器选择
        layout.addWidget(QLabel("解析器:"), 3, 0)
        self.parser_id_edit = QLineEdit()
        self.parser_id_edit.setText("naive")
        layout.addWidget(self.parser_id_edit, 3, 1)
        
        # 批次大小
        layout.addWidget(QLabel("批次大小:"), 4, 0)
        self.batch_size_spin = QSpinBox()
        self.batch_size_spin.setRange(1, 100)
        self.batch_size_spin.setValue(10)
        layout.addWidget(self.batch_size_spin, 4, 1, alignment=Qt.AlignLeft)
        
        # 文件列表
        layout.addWidget(QLabel("文件列表:"), 5, 0)
        
        # 创建文件列表
        self.files_list = QListWidget()
        layout.addWidget(self.files_list, 6, 0, 1, 2)
        
        # 按钮布局
        button_layout = QHBoxLayout()
        layout.addLayout(button_layout, 7, 0, 1, 2)
        
        # 刷新文件列表按钮
        refresh_button = QPushButton("刷新文件列表")
        refresh_button.clicked.connect(self.refresh_file_list)
        button_layout.addWidget(refresh_button)
        
        # 上传文件按钮
        upload_button = QPushButton("上传文件")
        upload_button.clicked.connect(self.upload_files)
        button_layout.addWidget(upload_button)
        
        # 添加弹性空间
        button_layout.addStretch()
    
    def __init__(self, parent=None):
        """初始化批量上传选项卡组件"""
        super().__init__(parent)
        self.parent = parent
        self.current_thread = None
        self.setup_ui()
        
        # 初始化加载知识库列表
        self.refresh_kb_list()
    
    def refresh_kb_list(self) -> None:
        """刷新知识库列表"""
        # 获取主窗口中的配置
        if not hasattr(self.parent, "get_config"):
            QMessageBox.critical(self, "错误", "无法获取配置信息")
            return
        
        config = self.parent.get_config()
        
        # 验证API配置
        if not config.api_url:
            QMessageBox.critical(self, "错误", "请先在配置页面设置API地址")
            return
        
        if not config.api_key:
            QMessageBox.critical(self, "错误", "请先在配置页面设置API密钥")
            return
        
        # 创建API客户端
        api = RagFlowAPI(config)
        
        # 显示加载中
        self.kb_combo.clear()
        self.kb_combo.addItem("加载中...")
        self.kb_combo.setEnabled(False)
        
        # 获取知识库列表
        try:
            from ragflow_client.utils.logger import get_logger
            logger = get_logger(__name__)
            
            # 记录API请求信息
            logger.debug(f"请求知识库列表: API URL={config.api_url}")
            
            success, result = api.list_datasets(page=1, page_size=100)
            
            # 清空下拉框
            self.kb_combo.clear()
            
            if success:
                # 处理不同的数据结构情况
                if isinstance(result, dict):
                    # 尝试获取数据，处理可能的不同结构
                    if "data" in result:
                        data = result["data"]
                        if isinstance(data, dict) and "items" in data:
                            datasets = data["items"]
                        elif isinstance(data, list):
                            datasets = data
                        else:
                            datasets = []
                    else:
                        datasets = []
                elif isinstance(result, list):
                    # 直接使用列表作为数据集
                    datasets = result
                else:
                    datasets = []
                
                if not datasets:
                    self.kb_combo.addItem("没有可用的知识库")
                    logger.warning("API返回成功但没有知识库数据")
                else:
                    # 添加知识库到下拉框
                    for dataset in datasets:
                        if isinstance(dataset, dict):
                            kb_id = dataset.get("id", "")
                            kb_name = dataset.get("name", "")
                            # 使用知识库名称作为显示文本，知识库ID作为用户数据
                            self.kb_combo.addItem(f"{kb_name} ({kb_id})", kb_id)
                        else:
                            logger.warning(f"跳过无效的知识库数据: {dataset}")
                    
                    # 连接选择变化信号
                    self.kb_combo.currentIndexChanged.connect(self.on_kb_selected)
                    
                    # 触发选择事件
                    if self.kb_combo.count() > 0:
                        self.kb_combo.setCurrentIndex(0)
                        self.on_kb_selected(0)
                        
                    logger.info(f"成功获取知识库列表，共 {len(datasets)} 个知识库")
            else:
                error_msg = f"获取知识库列表失败: {result}"
                self.kb_combo.addItem(error_msg)
                logger.error(error_msg)
                
                # 显示详细错误信息
                QMessageBox.critical(self, "API错误", 
                                    f"获取知识库列表失败\n\n"
                                    f"API地址: {config.api_url}\n"
                                    f"错误信息: {result}\n\n"
                                    f"请检查API地址是否正确，或者服务器是否可用。")
        
        except Exception as e:
            error_msg = f"获取知识库列表失败: {str(e)}"
            self.kb_combo.clear()
            self.kb_combo.addItem(error_msg)
            
            from ragflow_client.utils.logger import get_logger
            logger = get_logger(__name__)
            logger.error(error_msg)
            
            # 显示详细错误信息
            QMessageBox.critical(self, "错误", 
                                f"获取知识库列表失败\n\n"
                                f"API地址: {config.api_url}\n"
                                f"错误信息: {str(e)}\n\n"
                                f"请检查网络连接或API配置。")
        
        # 恢复下拉框状态
        self.kb_combo.setEnabled(True)
    
    def on_kb_selected(self, index: int) -> None:
        """
        处理知识库选择事件
        
        Args:
            index: 选中的索引
        """
        if index < 0:
            return
        
        # 获取选中的知识库ID
        self.kb_id = self.kb_combo.itemData(index)
        
        # 获取选中的知识库名称（去掉ID部分）
        kb_text = self.kb_combo.itemText(index)
        if "(" in kb_text and ")" in kb_text:
            self.kb_name = kb_text.split("(")[0].strip()
        else:
            self.kb_name = kb_text
    
    def browse_directory(self) -> None:
        """浏览文件夹"""
        directory = QFileDialog.getExistingDirectory(self, "选择文档目录")
        if directory:
            self.doc_dir_edit.setText(directory)
            self.refresh_file_list()
    
    def refresh_file_list(self) -> None:
        """刷新文件列表"""
        # 获取文档目录
        doc_dir = self.doc_dir_edit.text().strip()
        if not doc_dir:
            QMessageBox.critical(self, "错误", "请先选择文档目录")
            return
        
        # 获取文档后缀
        doc_suffix_str = self.doc_suffix_edit.text().strip()
        if not doc_suffix_str:
            QMessageBox.critical(self, "错误", "请先设置文档后缀")
            return
        
        doc_suffix = [s.strip() for s in doc_suffix_str.split(",") if s.strip()]
        
        # 获取文件列表
        try:
            files = get_files(doc_dir, doc_suffix)
            
            # 清空列表框
            self.files_list.clear()
            
            # 添加文件到列表框
            for file in files:
                # 显示相对路径
                rel_path = os.path.relpath(file, doc_dir)
                self.files_list.addItem(rel_path)
            
            # 显示文件数量
            QMessageBox.information(self, "文件列表", f"找到 {len(files)} 个文件")
            
        except Exception as e:
            QMessageBox.critical(self, "错误", f"获取文件列表失败: {str(e)}")
    
    def upload_files(self) -> None:
        """上传文件"""
        # 获取主窗口中的配置
        if not hasattr(self.parent, "get_config"):
            QMessageBox.critical(self, "错误", "无法获取配置信息")
            return
        
        config = self.parent.get_config()
        
        # 从界面获取知识库ID和解析器ID
        kb_id = self.kb_id
        parser_id = self.parser_id_edit.text().strip()
        
        # 从界面获取文档目录和后缀
        doc_dir = self.doc_dir_edit.text().strip()
        doc_suffix_str = self.doc_suffix_edit.text().strip()
        batch_size = self.batch_size_spin.value()
        
        # 验证必填字段
        if not config.api_url:
            QMessageBox.critical(self, "错误", "API 地址不能为空")
            return
        
        if not config.api_key:
            QMessageBox.critical(self, "错误", "API 密钥不能为空")
            return
        
        if not kb_id:
            QMessageBox.critical(self, "错误", "知识库 ID 不能为空")
            return
        
        if not doc_dir:
            QMessageBox.critical(self, "错误", "文档目录不能为空")
            return
        
        if not doc_suffix_str:
            QMessageBox.critical(self, "错误", "文档后缀不能为空")
            return
        
        # 解析文档后缀
        doc_suffix = [s.strip() for s in doc_suffix_str.split(",") if s.strip()]
        
        # 直接使用配置页面的配置，只修改特定字段
        upload_config = RagFlowConfig(
            api_url=config.api_url,  # 使用配置页面的API URL
            api_key=config.api_key,  # 使用配置页面的API密钥
            kb_id=kb_id,            # 使用选择的知识库ID
            kb_name=self.kb_name,   # 使用选择的知识库名称
            parser_id=parser_id,    # 使用输入的解析器ID
            doc_dir=doc_dir,        # 使用选择的文档目录
            doc_suffix=doc_suffix,  # 使用输入的文档后缀
            debug=config.debug,     # 使用配置页面的debug模式
            theme=config.theme      # 使用配置页面的主题设置
        )
        
        # 创建进度对话框
        progress = QProgressDialog("正在上传文件...", "取消", 0, 100, self)
        progress.setWindowTitle("批量上传文件")
        progress.setWindowModality(Qt.WindowModal)
        progress.setMinimumDuration(0)
        progress.setValue(0)
        progress.show()
        
        # 创建并启动工作线程
        self.current_thread = UploadFilesThread(upload_config, batch_size)
        self.current_thread.finished.connect(lambda status, msg: self.handle_upload_finished(status, msg, progress))
        self.current_thread.progress.connect(progress.setValue)
        self.current_thread.status_update.connect(lambda msg: self.log_message.emit(msg))
        self.current_thread.upload_result.connect(self.handle_upload_result)
        progress.canceled.connect(self.current_thread.cancel)
        self.current_thread.start()
    
    def handle_upload_finished(self, status: bool, msg: str, progress: QProgressDialog) -> None:
        """
        处理上传完成事件
        
        Args:
            status: 上传状态
            msg: 消息
            progress: 进度对话框
        """
        # 关闭进度对话框
        progress.close()
        
        # 如果没有成功，显示错误消息
        if not status:
            QMessageBox.critical(self, "错误", f"上传失败: {msg}")
        
        # 清理线程
        self.current_thread = None
    
    def handle_upload_result(self, success_count: int, failed_count: int) -> None:
        """
        处理上传结果
        
        Args:
            success_count: 成功数量
            failed_count: 失败数量
        """
        if failed_count == 0:
            QMessageBox.information(self, "成功", f"所有文件上传成功，共 {success_count} 个文件")
        else:
            QMessageBox.warning(self, "警告", f"部分文件上传失败，成功: {success_count}，失败: {failed_count}")
        
        # 发送上传结果信号
        self.upload_result.emit(success_count, failed_count)